/**
 * 
 */
package com.iss.card.common;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpStatus;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.iss.card.cache.ImageCache;
import com.iss.card.model.UserInfo;

/**
 * @author dtdh
 * 
 */
public class UploadFileUtil {
	public final static String USR_HEAD_ICON_TEMP_NAME = "user_tmp_icon";
	private final static String TAG = UploadFileUtil.class.getSimpleName();
	private final static String LINEND = System.getProperty("line.separator");
	private final static String BOUNDARY = "+++7da2137580612"; // seperator.
	private final static String PREFIX = "--";
	private final static int BUF_SIZE = 1024;
	private final static int CONNECT_TIME_OUT = 10000; // 10s

	/**
	 * upload file with stream.
	 * 
	 * @param serverUrl
	 *            server url.
	 * @param file
	 *            file with stream.
	 * @param uid
	 *            current login user's id.
	 */
	public static void upload(String serverUrl, InputStream file, String uid) {
		Log.d(TAG, "upload: " + serverUrl + ", " + uid);
		HttpURLConnection con;
		try {
			URL url = new URL(serverUrl);
			con = (HttpURLConnection) url.openConnection();
			/* allow input, output and disable cache. */
			con.setDoInput(true);
			con.setDoOutput(true);
			con.setUseCaches(false);
			con.setConnectTimeout(CONNECT_TIME_OUT);

			/* set request method as POST */
			con.setRequestMethod("POST");
			con.setRequestProperty("Charset", "UTF-8");
			con.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + BOUNDARY);

			/* set DataOutputStream */
			DataOutputStream ds = new DataOutputStream(con.getOutputStream());

			/* send parameter data. */
			Map<String, String> datas = new HashMap<String, String>();
			datas.put("type", "png");
			datas.put("action", "memberheadpic");
			datas.put("id", uid);
			ds.write(buildParameterFormField(datas).getBytes());

			// send image data.
			ds.write(buildImageContentField().getBytes());
			byte[] buffer = new byte[BUF_SIZE];
			int length = -1;
			while ((length = file.read(buffer)) != -1) {
				ds.write(buffer, 0, length);
			}
			ds.write(LINEND.getBytes());

			// send end line of form data.
			ds.write((PREFIX + BOUNDARY + PREFIX + LINEND).getBytes());

			// read response from server.
			readResponse(con);

			file.close();
			ds.flush();
			ds.close();
			Log.d(TAG, "upload completed");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * upload file with file name.
	 * 
	 * @param serverUrl
	 *            server url.
	 * @param filePath
	 *            file name.
	 * @param uid
	 *            current login user's id.
	 */
	public static void upload(String serverUrl, String filePath, String uid) {
		Log.d(TAG, "upload: " + serverUrl + ", " + filePath + ", " + uid);
		try {
			upload(serverUrl, new FileInputStream(filePath), uid);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * build form field which format as following:</p> --+++7dd2cb590bc2
	 * (separator line.) </p> Content-Disposition: form-data; name="fid" (key)
	 * </p> fpStorePic (value) </p> --+++7dd2cb590bc2 (separator line.) </p>
	 * Content-Disposition: form-data; name="filetype" (key) </p> storepic
	 * (value) </p> --+++7dd2cb590bc2 (separator line.) </p>
	 * Content-Disposition: form-data; name="fpStorePic";
	 * filename="Tulips.jpg"(key) </p> Content-Type: image/jpeg </p> (space
	 * line) </p> binary data for image. (content data with binary) </p>
	 * --+++7dd2cb590bc2--\r\n (end line) </p>
	 * 
	 * @param params
	 *            form field data.
	 * @return form with data.
	 */
	private static String buildParameterFormField(Map<String, String> params) {
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<String, String> entry : params.entrySet()) {
			sb.append(PREFIX + BOUNDARY + LINEND);
			sb.append("Content-Disposition: form-data; name=\""
					+ entry.getKey() + "\"" + LINEND);
			sb.append(LINEND);
			sb.append(entry.getValue() + LINEND);
		}
		return sb.toString();
	}

	/**
	 * build image content field. please refer comment in buildFormField().
	 * 
	 * @return form with content image data.
	 */
	private static String buildImageContentField() {
		StringBuilder sb = new StringBuilder();
		sb.append(PREFIX + BOUNDARY + LINEND);
		sb.append("Content-Disposition: form-data; name=\"" + "usr_icon_file"
				+ "\"; filename=\"" + "abc.png" + "\"" + LINEND);
		sb.append("Content-Type: image/png" + LINEND);
		sb.append(LINEND);

		return sb.toString();
	}

	/**
	 * read response and save icon url while it is success.
	 * {"success":true,"url":"/upload/MemberHeadPic/User675.jpg"}
	 * 
	 * @param con
	 *            Http URL connection.
	 * @throws IOException
	 * @throws JSONException
	 */
	private static void readResponse(HttpURLConnection con) throws IOException,
			JSONException {
		String msg = "";
		if (con.getResponseCode() == HttpStatus.SC_OK) {
			BufferedReader ibd = new BufferedReader(new InputStreamReader(
					con.getInputStream()));
			msg = ibd.readLine();
			JSONObject obj = new JSONObject(msg);
			final boolean success = Boolean.valueOf(obj.getString("success"));
			String result = "";
			if (success) {
				result = obj.getString("url");
				ImageCache.instance().renameCachedName(USR_HEAD_ICON_TEMP_NAME, result);
				UserInfo usr = FunctionUtil.getCurrentLogInUser();
				usr.setUsrHeadIconUrl(result);
				FunctionUtil.saveCurrentLogInUser(usr);
			} else {
				// TODO failed to submit.
				result = obj.getString("error");
				ImageCache.instance().deleteBitmapFromCache(USR_HEAD_ICON_TEMP_NAME);
			}
		} else {
			// TODO Network NG.
			ImageCache.instance().deleteBitmapFromCache(USR_HEAD_ICON_TEMP_NAME);			
		}

		Log.d(TAG, "upload: response=[" + msg + "]");
	}
}
